package org.dicr.gui;

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;

import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;

import org.dicr.event.*;
import org.dicr.gui.io.*;
import org.dicr.gui.res.*;

/***********************************************************************************************************************
 * @author Igor A Tarasov, me@dicr.dn.ua
 * @version 021122
 **********************************************************************************************************************/
public class DocumentEditorPanel extends JPanel implements ActionListener, Editable {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	protected JScrollPane scroll = new JScrollPane();

	protected JEditorPane editor = new JEditorPane();

	protected ControlPanel controlPanel = new ControlPanel();

	protected JButton loadButton = new JButton();

	protected JButton newButton = new JButton();

	protected JButton saveButton = new JButton();

	protected JButton[] buttons = new JButton[] { this.loadButton, this.saveButton, this.newButton };

	protected Vector<ChangeListener> listeners = new Vector<ChangeListener>();

	protected DocumentIO docIO = new DocumentIO();

	protected boolean changed = true;

	protected boolean editable = true;

	/*******************************************************************************************************************
	 * Конструктор
	 ******************************************************************************************************************/
	public DocumentEditorPanel() {
		try {
			jbInit();
		} catch (Exception ex) {
			DicrExceptionHandler.handleException(ex, this);
		}
	}

	/*******************************************************************************************************************
	 * Инициализация
	 ******************************************************************************************************************/
	private void jbInit() {
		ResourceManager.setButtonReource(this.loadButton, "icons/Open24.gif", "Загрузить",
		        "Загрузить документ из файла");
		ResourceManager.setButtonReource(this.saveButton, "icons/Save24.gif", "Сохранить", "Сохранить документ в файл");
		ResourceManager.setButtonReource(this.newButton, "icons/New24.gif", "Новый документ", "Создать новый документ");
		Insets margin = new Insets(0, 0, 0, 0);
		for (int i = 0; i < this.buttons.length; i++) {
			JButton button = this.buttons[i];
			button.addActionListener(this);
			button.setMargin(margin);
			this.controlPanel.add(button);
		}
		this.editor.setAutoscrolls(true);
		this.scroll.setViewportView(this.editor);
		this.setLayout(new BorderLayout());
		this.add(this.scroll, BorderLayout.CENTER);
		this.add(this.controlPanel, BorderLayout.NORTH);
		this.setPreferredSize(new Dimension(400, 300));
	}

	/*******************************************************************************************************************
	 * Устанавливает content-type документа
	 ******************************************************************************************************************/
	public void setContentType(String contentType) {
		this.editor.setContentType(contentType);
		fireChangeEvent();
	}

	/*******************************************************************************************************************
	 * Возвращает content-type документа
	 ******************************************************************************************************************/
	public String getContentType() {
		return this.editor.getContentType();
	}

	/*******************************************************************************************************************
	 * Установка нового документа
	 ******************************************************************************************************************/
	public void setDocument(Document doc) {
		if (this.editor.getDocument() != doc) {
			this.editor.setDocument(doc);
			fireChangeEvent();
		}
	}

	/*******************************************************************************************************************
	 * Возвращает текущий документ
	 ******************************************************************************************************************/
	public Document getDocument() {
		return this.editor.getDocument();
	}

	/*******************************************************************************************************************
	 * Устанавливает признак редактируемости
	 ******************************************************************************************************************/
	@Override
    public void setEditable(boolean theEditable) {
		if (this.editable != theEditable) {
			this.editable = theEditable;
			this.editor.setEditable(theEditable);
		}
	}

	/*******************************************************************************************************************
	 * Возвращает признак редактируемости
	 ******************************************************************************************************************/
	@Override
    public boolean isEditable() {
		return this.editable;
	}

	/*******************************************************************************************************************
	 * Выводит окно выбора файла и загружает выбранный файл
	 ******************************************************************************************************************/
	public boolean loadDocument() throws BadLocationException, IOException {
		boolean ret = false;
		if (this.docIO.loadDocument(this, this.editor)) {
			fireChangeEvent();
			ret = true;
		}
		return ret;
	}

	/*******************************************************************************************************************
	 * Выводит диалог выбора файла и сохраняет файл
	 ******************************************************************************************************************/
	public boolean saveDocument() throws BadLocationException, IOException {
		boolean ret = false;
		if (this.docIO.saveDocument(this.editor, this)) {
			ret = true;
		}
		return ret;
	}

	/*******************************************************************************************************************
	 * Очищает документ. Создает создает новый пустой документ вместо текущего.
	 ******************************************************************************************************************/
	public void clearDocument() {
		this.docIO.initDocument(this.editor);
		fireChangeEvent();
	}

	/*******************************************************************************************************************
	 * Обработка событий кнопок
	 ******************************************************************************************************************/
	@Override
    public void actionPerformed(ActionEvent e) {
		try {
			Object src = e.getSource();
			if (src == this.loadButton) loadDocument();
			else if (src == this.saveButton) saveDocument();
			else if (src == this.newButton) clearDocument();
		} catch (Exception ex) {
			DicrExceptionHandler.handleException(ex, this, true);
		}
	}

	/*******************************************************************************************************************
	 * Добавляет слушателя изменений
	 ******************************************************************************************************************/
	public void addChangeListener(ChangeListener l) {
		if (l != null && !this.listeners.contains(l)) this.listeners.add(l);
	}

	/*******************************************************************************************************************
	 * Удаляет слушателя изменений
	 ******************************************************************************************************************/
	public void removeChangeListener(ChangeListener l) {
		this.listeners.remove(l);
	}

	/*******************************************************************************************************************
	 * Оповещает слушателей
	 ******************************************************************************************************************/
	public void fireChangeEvent() {
		for (int i = 0; i < this.listeners.size(); i++)
			try {
				this.listeners.get(i).stateChanged(new ChangeEvent(this));
			} catch (Exception ex) {
				DicrExceptionHandler.handleException(ex, this);
			}
	}
}
